package net.goutalk.glcs.module.workflow.listener;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.TypeReference;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import net.goutalk.glcs.common.constant.GlobalConstant;
import net.goutalk.glcs.common.enums.*;
import net.goutalk.glcs.common.utils.RedisUtil;
import net.goutalk.glcs.module.organization.entity.User;
import net.goutalk.glcs.module.organization.entity.UserRoleRelation;
import net.goutalk.glcs.module.organization.service.IUserService;
import net.goutalk.glcs.module.workflow.constant.WorkflowConstant;
import net.goutalk.glcs.module.workflow.entity.*;
import net.goutalk.glcs.module.workflow.model.*;
import net.goutalk.glcs.module.workflow.service.*;
import net.goutalk.glcs.module.workflow.service.*;
import net.goutalk.glcs.module.workflow.utils.WorkFlowUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.goutalk.glcs.common.enums.*;
import net.goutalk.glcs.module.workflow.entity.*;
import net.goutalk.glcs.module.workflow.model.NoticePolicyParam;
import net.goutalk.glcs.module.workflow.model.TimeoutRemidConfig;
import net.goutalk.glcs.module.workflow.model.UserTaskConfig;
import net.goutalk.glcs.module.workflow.model.WorkflowSchemaConfig;
import org.camunda.bpm.engine.RuntimeService;
import org.camunda.bpm.engine.TaskService;
import org.camunda.bpm.engine.delegate.DelegateTask;
import org.camunda.bpm.engine.delegate.TaskListener;
import org.camunda.bpm.engine.task.Task;
import org.springframework.stereotype.Component;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 任务监听器
 *
 * @Author: tanyujie
 * @Date: 2022/12/7 16:28
 */
@Component
@Slf4j
@AllArgsConstructor
public class TaskDelegate implements TaskListener {

    private final RedisUtil redisUtil;

    private final IWorkflowDelegateService workflowDelegateService;

    private final IWorkflowCirculatedService circulatedService;

    private final IUserService userService;

    private Map<String,ScriptEngine> scriptEngineMap;


//    private final IWorkflowSchemaService workflowSchemaService;

    @Override
    public void notify(DelegateTask delegateTask) {
        //判断事件类型 如果是创建  (如果是单元测试代码 需要注释此代码)
        if (delegateTask.getEventName().equals(EVENTNAME_CREATE)) {
            log.info("[用户任务监听器] 事件: {}", delegateTask.getEventName());

            List<String> variableNames = ListUtil.toList(
                    WorkflowConstant.PROCESS_SCHEMA_ID_KEY,
                    WorkflowConstant.PROCESS_SCHEMA_NAME_KEY,
                    WorkflowConstant.PROCESS_START_USER_ID_KEY,
                    WorkflowConstant.PROCESS_START_USER_NAME_KEY,
                    WorkflowConstant.PROCESS_SERIAL_NUMBER_KEY,
                    WorkflowConstant.PROCESS_NAME);

            RuntimeService runtimeService = delegateTask.getProcessEngine().getRuntimeService();

            Map<String, Object> variableMaps = runtimeService.getVariables(delegateTask.getProcessInstanceId(), variableNames);

            IWorkflowSchemaService workflowSchemaService = SpringUtil.getBean(IWorkflowSchemaService.class);
            WorkflowSchema workflowSchema = workflowSchemaService.getOne(Wrappers.lambdaQuery(WorkflowSchema.class).eq(WorkflowSchema::getId, MapUtil.getLong(variableMaps, WorkflowConstant.PROCESS_SCHEMA_ID_KEY)));
//            WorkflowSchema workflowSchema = redisUtil.get(WorkflowConstant.SCHEMA_CACHE_PREFIX + MapUtil.getStr(variableMaps, WorkflowConstant.PROCESS_SCHEMA_ID_KEY), WorkflowSchema.class);

            if (workflowSchema == null) {
                workflowSchema = workflowSchemaService.getById(MapUtil.getLong(variableMaps, WorkflowConstant.PROCESS_SCHEMA_ID_KEY));
            }
            WorkflowSchemaConfig workflowSchemaConfig = JSONUtil.toBean(workflowSchema.getJsonContent(), WorkflowSchemaConfig.class);

            Optional<Map<String, Object>> userTaskConfigOp = workflowSchemaConfig.getChildNodeConfig().stream().filter(c -> c.containsValue(delegateTask.getTaskDefinitionKey())).findFirst();

            if (!userTaskConfigOp.isPresent()) {
                return;
            }
            //将map 转为 java类
            UserTaskConfig userTaskConfig = Convert.convert(UserTaskConfig.class, userTaskConfigOp.get());

            //设置超时提醒
            setTimeoutRemid(delegateTask, workflowSchemaConfig, userTaskConfig);

            //多实例任务 会在 流程线 执行监听器 就设置了人员List   会自动生成审批人变量
            initApproveUser(delegateTask, workflowSchemaConfig, userTaskConfig, variableMaps);

            //设置自定义任务名称规则
            setProcessExtra(delegateTask, variableMaps, workflowSchema, workflowSchemaConfig, userTaskConfig);


        }

        //如果是审批事件  判断当前任务 是否有按钮事件
        if(delegateTask.getEventName().equals(EVENTNAME_COMPLETE)){

            if(redisUtil.containsKey(WorkflowConstant.BUTTON_EVENT_CACHE_PRE + delegateTask.getId())){
                Map<String, Object> map = redisUtil.get(WorkflowConstant.BUTTON_EVENT_CACHE_PRE + delegateTask.getId(), new TypeReference<Map<String, Object>>() {
                });
                Integer language = MapUtil.get(map, "language", Integer.class);
                String content = MapUtil.get(map, "content", String.class);

                String scriptvar = "execution";

                ScriptEngine scriptEngine;

                if (ObjectUtil.isNotEmpty(language) && StrUtil.isNotBlank(content)){
                    if(language == 0){
                        String JAVA_SCRIPT = "js";
                        if(scriptEngineMap.containsKey(JAVA_SCRIPT)){
                            scriptEngine = scriptEngineMap.get(JAVA_SCRIPT);
                        }
                        else {
                            scriptEngine = new ScriptEngineManager().getEngineByName(JAVA_SCRIPT);
                            scriptEngineMap.put(JAVA_SCRIPT,scriptEngine);
                        }
                    }
                    else{
                        String GROOVY = "groovy";
                        if(scriptEngineMap.containsKey(GROOVY)){
                            scriptEngine = scriptEngineMap.get(GROOVY);
                        }
                        else {
                            scriptEngine = new ScriptEngineManager().getEngineByName(GROOVY);
                            scriptEngineMap.put(GROOVY,scriptEngine);
                        }
                    }

                    // 方式一，默认设置变量
                    scriptEngine.put(scriptvar, delegateTask);

                    try {

                        redisUtil.delete(WorkflowConstant.BUTTON_EVENT_CACHE_PRE + delegateTask.getId());
                        scriptEngine.eval(content);

                    }
                    catch (Exception e){
                        e.printStackTrace();
                    }
                }
                else {
                    redisUtil.delete(WorkflowConstant.BUTTON_EVENT_CACHE_PRE + delegateTask.getId());
                }
            }
        }

    }

    /**
     * 设置用户传阅人
     *
     * @param delegateTask
     * @param variableMaps
     * @param workflowSchemaConfig
     * @param userTaskConfig
     */
    private void initCirculatedUser(DelegateTask delegateTask, Map<String, Object> variableMaps, WorkflowSchemaConfig workflowSchemaConfig, UserTaskConfig userTaskConfig, Long id) {
        if (userTaskConfig.getCirculateConfigs() == null) {
            return;
        }
        //获取到用户节点的传阅人
        List<Long> nextUserTaskCirculated = WorkFlowUtil.getUserIdsByMemberConfig(userTaskConfig.getCirculateConfigs(), workflowSchemaConfig.getChildNodeConfig(),delegateTask.getProcessInstanceId());

        //多实例流程不记录传阅人消息
        if (userTaskConfig.getCountersignConfig().getMultipleInstancesType() == WorkflowMultiInstanceType.NONE.getCode()) {
            List<WorkflowCirculated> circulatedList = new ArrayList<>();
            for (Long userId : nextUserTaskCirculated) {
                WorkflowCirculated workflowCirculated = new WorkflowCirculated();
                workflowCirculated.setProcessId(delegateTask.getProcessInstanceId());
                workflowCirculated.setCreateTime(DateUtil.toLocalDateTime(delegateTask.getCreateTime()));
                workflowCirculated.setTaskId(delegateTask.getId());
                workflowCirculated.setCurrentProgress(userTaskConfig.getCurrentProgress());
                workflowCirculated.setTaskName(delegateTask.getName());
                workflowCirculated.setIsRead(YesOrNoEnum.NO.getCode());
                workflowCirculated.setProcessName(MapUtil.getStr(variableMaps, WorkflowConstant.PROCESS_NAME));
                workflowCirculated.setSchemaId(MapUtil.getLong(variableMaps, WorkflowConstant.PROCESS_SCHEMA_ID_KEY));
                workflowCirculated.setCirculatedUserId(userId);
                workflowCirculated.setStartUserId(MapUtil.getLong(variableMaps, WorkflowConstant.PROCESS_START_USER_ID_KEY));
                workflowCirculated.setSerialNumber(MapUtil.getLong(variableMaps, WorkflowConstant.PROCESS_SERIAL_NUMBER_KEY));
                circulatedList.add(workflowCirculated);

            }

            NoticePolicyParam param = new NoticePolicyParam();
            param.setNoticeUserIds(nextUserTaskCirculated);
            param.setTaskId(delegateTask.getId());
            param.setTaskName(delegateTask.getName());
            param.setProcessId(delegateTask.getProcessInstanceId());
            param.setTaskName(delegateTask.getName());
            param.setSchemaId(MapUtil.get(variableMaps, WorkflowConstant.PROCESS_SCHEMA_ID_KEY, Long.class));
            param.setSchemaName(MapUtil.get(variableMaps, WorkflowConstant.PROCESS_SCHEMA_NAME_KEY, String.class));
            param.setStartUserName(MapUtil.get(variableMaps, WorkflowConstant.PROCESS_START_USER_NAME_KEY, String.class));
            param.setNoticePolicyConfigs(userTaskConfig.getNoticePolicyConfigs());
            WorkFlowUtil.sendCirculatedNoticePolicy(param,delegateTask.getName());

            circulatedService.saveBatch(circulatedList);
        }
        //当前传阅人[所有传阅人名称]
        String circulatedName = WorkFlowUtil.getAllUserNamesByIds(nextUserTaskCirculated);
        //如果当前传阅人不为空，就给上面那条准备审批信息中间加上传阅人信息
        if (StrUtil.isNotBlank(circulatedName)) {
            IWorkflowRecordService workflowRecordService = SpringUtil.getBean(IWorkflowRecordService.class);
            WorkflowRecord record = new WorkflowRecord();
            record.setId(id);
            record.setCirculateMessage("当前传阅人【" + circulatedName + "】");
            workflowRecordService.updateById(record);
        }
//        addProcessRecord(delegateTask, MapUtil.getLong(variableMaps, WorkflowConstant.PROCESS_SCHEMA_ID_KEY), "当前传阅人【"+circulatedName+"】");
    }

    /**
     * 设置审批人
     * 然后 判断是否自动通过
     * 新增 流程记录
     *
     * @param delegateTask
     * @param workflowSchemaConfig
     * @param userTaskConfig
     * @return 是否指定审批人
     */
    private void initApproveUser(DelegateTask delegateTask, WorkflowSchemaConfig workflowSchemaConfig, UserTaskConfig userTaskConfig, Map<String, Object> variableMaps) {
        TaskService taskService = delegateTask.getProcessEngine().getTaskService();
        taskService.setVariableLocal(delegateTask.getId(), WorkflowConstant.TASK_IS_APPOINT_APPROVE, YesOrNoEnum.NO.getCode());


        Long schemaId = MapUtil.get(variableMaps, WorkflowConstant.PROCESS_SCHEMA_ID_KEY, Long.class);

        List<Long> approveUserIds = new ArrayList<>();

        // 如果是单实例
        if (userTaskConfig.getCountersignConfig().getMultipleInstancesType() == WorkflowMultiInstanceType.NONE.getCode()) {

            //获取到所有审批人
            approveUserIds = WorkFlowUtil.getUserIdsByMemberConfig(userTaskConfig.getApproverConfigs(), workflowSchemaConfig.getChildNodeConfig(),delegateTask.getProcessInstanceId());

            //如果节点设置了指定审批人 就不再走无对应处理人逻辑
            if (userTaskConfig.getIsPrevChooseNext() == WorkflowIsPrevChooseNextType.PREV.getCode()) {
                taskService.setVariableLocal(delegateTask.getId(), WorkflowConstant.TASK_ASSIGNEE_VAR_KEY, StrUtil.join(StringPool.COMMA, approveUserIds));
                return;
            }

            //如果全局设置了指定审批人 就不再走无对应处理人逻辑
            if (workflowSchemaConfig.getProcessConfig().getIsPrevChooseNext() == WorkflowIsPrevChooseNextType.PREV.getCode()) {
                taskService.setVariableLocal(delegateTask.getId(), WorkflowConstant.TASK_ASSIGNEE_VAR_KEY, StrUtil.join(StringPool.COMMA, approveUserIds));
                return;
            }

            //无对应处理人
            if (userTaskConfig.getApproverConfigs().size() == 0 || approveUserIds.size() == 0) {

                //如果节点配置了 无对应处理人 为admin 默认覆盖 全局设置
                if (userTaskConfig.getNoHandler() == WorkflowNoHandlerType.ADMIN.getCode()) {
                    List<UserRoleRelation> userRoleRelations = redisUtil.get(GlobalConstant.USER_ROLE_RELATION_CACHE_KEY, new TypeReference<List<UserRoleRelation>>() {
                    });
                    //获取超级管理员成员
                    List<Long> adminUserIds = userRoleRelations.stream().filter(x -> x.getRoleId().equals(GlobalConstant.SUPER_ADMIN_ROLE_ID)).map(UserRoleRelation::getUserId).collect(Collectors.toList());
                    //根据用户id获取对应的用户名，并进行拼接输出（张三、李四这种）
                    approveUserIds = adminUserIds;
                    taskService.setVariableLocal(delegateTask.getId(), WorkflowConstant.TASK_ASSIGNEE_VAR_KEY, StrUtil.join(StringPool.COMMA, adminUserIds));

                }

            } else {
                //根据所选审批人 找到审批人 新增到 所选审批人中。
                setUserDelegate(delegateTask,  schemaId, approveUserIds);
                taskService.setVariableLocal(delegateTask.getId(), WorkflowConstant.TASK_ASSIGNEE_VAR_KEY, StrUtil.join(StringPool.COMMA, approveUserIds));

            }
        }
        //多实例 不可能没有处理人 因为多实例如果不设置处理人 不会生成task  但是会需要判断是否自动同意
        else {

            //如果有这个key  就是代表 会签节点有设置过审批人id
            if(redisUtil.containsKey(WorkflowConstant.MULTI_ASSIGNEE_CACHE_PREFIX + delegateTask.getExecutionId())){
                String approveId = redisUtil.get(WorkflowConstant.MULTI_ASSIGNEE_CACHE_PREFIX + delegateTask.getExecutionId());
                approveUserIds.add(Convert.toLong(approveId));
                taskService.setVariableLocal(delegateTask.getId(), WorkflowConstant.TASK_ASSIGNEE_VAR_KEY, approveId);
                redisUtil.delete(delegateTask.getExecutionId());
            }
        }
        String approveName = WorkFlowUtil.getAllUserNamesByIds(approveUserIds);
        Long recordId = addProcessRecord(delegateTask, schemaId, "【" + approveName + "】" + "准备审批");
        //设置用户传阅人
        initCirculatedUser(delegateTask, variableMaps, workflowSchemaConfig, userTaskConfig, recordId);
        //默认所有任务不需要指定审批人  如果需要指定审批人 会在 launch  和 approve 接口 处理。

    }

    /**
     * 根据所选审批人 找到委托人 新增到 所选审批人中。
     *
     * @param schemaId
     * @param approveUserIds
     */
    private void setUserDelegate(DelegateTask delegateTask, Long schemaId, List<Long> approveUserIds) {
        //查询下一个节点审批人 委托 数据  将被委托人加入到 审批人数据中
        LambdaQueryWrapper<WorkflowDelegate> wrapper = Wrappers.lambdaQuery(WorkflowDelegate.class)
                .in(WorkflowDelegate::getUserId, approveUserIds)
                .lt(WorkflowDelegate::getStartTime, DateUtil.parse(DateUtil.now()).toJdkDate())
                .gt(WorkflowDelegate::getEndTime, DateUtil.parse(DateUtil.now()).toJdkDate())
                .like(WorkflowDelegate::getSchemaIds, schemaId)
                .select(WorkflowDelegate::getDelegateUserIds);
        List<WorkflowDelegate> workflowDelegates = workflowDelegateService.list(wrapper);

        if (workflowDelegates.size() > 0) {

            List<String> allDelegateStr = workflowDelegates.stream().map(WorkflowDelegate::getDelegateUserIds).collect(Collectors.toList());

            List<Long> allDelegateUserIds = Arrays.stream(StrUtil.join(StringPool.COMMA, allDelegateStr).split(StringPool.COMMA)).map(Convert::toLong).collect(Collectors.toList());
            approveUserIds.addAll(allDelegateUserIds);

            //新增流程发起流程记录
            //获取当前用户的信息
            User user = StpUtil.getTokenSession().get(GlobalConstant.LOGIN_USER_INFO_KEY, new User());
            //根据用户id获取对应的用户名，并进行拼接输出
            String allDelegateUserNames = WorkFlowUtil.getAllUserNamesByIds(allDelegateUserIds);
            //[操作人名称]通过[流程委托]委托[被委托人名称]作为审批人
            String message = "【" + user.getName() + "】通过【流程委托】委托【" + allDelegateUserNames + "】作为审批人";
            addProcessRecord(delegateTask, schemaId, message);
        }
    }

    /**
     * 是否自动同意
     *
     * @param delegateTask
     */
    private void setAutoAgree(DelegateTask delegateTask, WorkflowSchemaConfig workflowSchemaConfig, Long schemaId, List<Long> approveUserIds) {

        List<Integer> autoAgreeRule = workflowSchemaConfig.getProcessConfig().getAutoAgreeRule();

        TaskService taskService = delegateTask.getProcessEngine().getTaskService();
        //如果没有配置过  默认跳过
        if (autoAgreeRule != null && autoAgreeRule.size() > 0) {

            User user = StpUtil.getTokenSession().get(GlobalConstant.LOGIN_USER_INFO_KEY, new User());

            //新增流程发起流程记录
            String opinion = StringPool.EMPTY;

            //候选审批人包含流程任务发起人
            if (autoAgreeRule.contains(WorkflowAutoAgreeType.APPROVED_INCLUDE_INITIATOR.getCode())) {
                //模板id
                Object startUserId = delegateTask.getVariable(WorkflowConstant.PROCESS_START_USER_ID_KEY);
                if (approveUserIds.contains(Convert.toLong(startUserId))) {

                    taskService.createComment(delegateTask.getId(), delegateTask.getProcessInstanceId(), "候选审批人包含流程任务发起人---自动同意");
                    taskService.complete(delegateTask.getId());

                    opinion = "候选审批人包含流程任务发起人";
                }
            }
            //候选审批人包含上一节点审批人
            if (autoAgreeRule.contains(WorkflowAutoAgreeType.APPROVED_INCLUDE_PREV.getCode())) {
                //当前操作人 就是上一结点审批人
                if (approveUserIds.contains(StpUtil.getLoginIdAsLong())) {
                    taskService.createComment(delegateTask.getId(), delegateTask.getProcessInstanceId(), "候选审批人包含上一节点审批人---自动同意");
                    taskService.complete(delegateTask.getId());

                    opinion = "候选审批人包含上一节点审批人";
                }
            }
            //候选审批人在此流程中审批过
            if (autoAgreeRule.contains(WorkflowAutoAgreeType.APPROVED_IN_PROCESS.getCode())) {
                //模板id
                Object startUserId = delegateTask.getVariable(WorkflowConstant.PROCESS_START_USER_ID_KEY);


                if (approveUserIds.contains(Convert.toLong(startUserId))) {
                    taskService.createComment(delegateTask.getId(), delegateTask.getProcessInstanceId(), "候选审批人在此流程中审批过---自动同意");
                    taskService.complete(delegateTask.getId());
                } else {
                    if (redisUtil.containsKey(WorkflowConstant.TASK_ASSIGNEE_RECORD_VAR_KEY)) {
                        Map<String, List<Long>> taskAssigneeRecordMap = redisUtil.get(WorkflowConstant.TASK_ASSIGNEE_RECORD_VAR_KEY, new TypeReference<Map<String, List<Long>>>() {
                        });

                        for (String taskId : taskAssigneeRecordMap.keySet()) {
                            List<Long> userIds = taskAssigneeRecordMap.get(taskId);

                            if (userIds.retainAll(approveUserIds)) {
                                taskService.createComment(delegateTask.getId(), delegateTask.getProcessInstanceId(), "候选审批人在此流程中审批过---自动同意");
                                taskService.complete(delegateTask.getId());
                            }

                        }

                    }
                }

                opinion = "候选审批人在此流程中审批过";
            }

            //缓存 自动通过 记录
            WorkFlowUtil.cacheTaskAssigneeRecord(delegateTask.getProcessInstanceId(), delegateTask.getId(), StpUtil.getLoginIdAsLong());

            List<Task> list = taskService.createTaskQuery().processInstanceId(delegateTask.getProcessInstanceId()).list();
            //如果找不到任务了 默认流程已经结束
            if (list.size() > 0) {

                String allNextTaskName = StrUtil.join(StringPool.SPACE, list.parallelStream().map(t -> "【" + t.getName() + "】").collect(Collectors.toList()));

                String message = "【" + user.getName() + "】【自动同意】 审批, 审批意见为：“【" + opinion + "】”，由【" + delegateTask.getName() + "】流转到 " + allNextTaskName;
                addProcessRecord(delegateTask, schemaId, message);
            } else {
                String message = "【" + user.getName() + "】【自动同意】 审批, 审批意见为：“【" + opinion + "】”，由【" + delegateTask.getName() + "】流转到 结束节点";
                addProcessRecord(delegateTask, schemaId, message);

            }

        }

    }

    /**
     * 添加流程记录
     */
    private Long addProcessRecord(DelegateTask delegateTask, Long schemaId, String message) {

        IWorkflowRecordService workflowRecordService = SpringUtil.getBean(IWorkflowRecordService.class);
        //新增流程发起流程记录
        WorkflowRecord record = new WorkflowRecord();
        record.setNodeId(delegateTask.getId());
        record.setNodeName(delegateTask.getName());
        record.setNodeType(WorkflowConstant.START_EVENT_TYPE_NAME);
        record.setProcessId(delegateTask.getProcessInstanceId());
        record.setSchemaId(schemaId);
        record.setNodeMultiType(WorkflowMultiInstanceType.NONE.getCode());
        record.setRecordTime(LocalDateTime.now());

        record.setMessage(message);

        workflowRecordService.save(record);

        return record.getId();
    }

    /**
     * 设置根据命名规则 设置任务名字
     *
     * @param delegateTask
     */
    private void setProcessExtra(DelegateTask delegateTask, Map<String, Object> variableMaps, WorkflowSchema workflowSchema, WorkflowSchemaConfig workflowSchemaConfig, UserTaskConfig userTaskConfig) {

        WorkflowExtra extra = new WorkflowExtra();
        extra.setProcessId(delegateTask.getProcessInstanceId());
        extra.setTaskId(delegateTask.getId());
        extra.setTaskKey(delegateTask.getTaskDefinitionKey());
        extra.setStartUserId(MapUtil.getLong(variableMaps, WorkflowConstant.PROCESS_START_USER_ID_KEY));
        extra.setStartUserName(MapUtil.getStr(variableMaps, WorkflowConstant.PROCESS_START_USER_NAME_KEY));
        extra.setProcessName(MapUtil.getStr(variableMaps, WorkflowConstant.PROCESS_NAME));
        extra.setSchemaId(MapUtil.getLong(variableMaps, WorkflowConstant.PROCESS_SCHEMA_ID_KEY));
        extra.setSchemaName(MapUtil.getStr(variableMaps, WorkflowConstant.PROCESS_SCHEMA_NAME_KEY));
        extra.setSerialNumber(MapUtil.getLong(variableMaps, WorkflowConstant.PROCESS_SERIAL_NUMBER_KEY));
        extra.setStartTime(LocalDateTime.now());
        extra.setLaunchTime(DateUtil.toLocalDateTime(delegateTask.getCreateTime()));
        extra.setCurrentProgress(userTaskConfig.getCurrentProgress());

        TaskService taskService = delegateTask.getProcessEngine().getTaskService();

        Object variable = taskService.getVariable(delegateTask.getId(), WorkflowConstant.TASK_ASSIGNEE_VAR_KEY);
        extra.setApproveUserIds(Convert.toStr(variable));

        extra.setTaskName(delegateTask.getName());


        IWorkflowExtraService workflowExtraService = SpringUtil.getBean(IWorkflowExtraService.class);
        workflowExtraService.save(extra);


    }


    /**
     * 设置超时提醒定时任务
     */
    private void setTimeoutRemid(DelegateTask delegateTask, WorkflowSchemaConfig
            workflowSchemaConfig, UserTaskConfig userTaskConfig) {

        if (workflowSchemaConfig.getProcessConfig().getTimeoutRemidConfig() == null) return;

        TimeoutRemidConfig timeoutRemidConfig = workflowSchemaConfig.getProcessConfig().getTimeoutRemidConfig();

        if (timeoutRemidConfig.getEnabled()) {
            //获取到所有需要提示的人员
            List<Long> userIdsByMemberConfig = WorkFlowUtil.getUserIdsByMemberConfig(timeoutRemidConfig.getPushMemberConfigs(), workflowSchemaConfig.getChildNodeConfig(),delegateTask.getProcessInstanceId());
            List<Long> approveUserIds = WorkFlowUtil.getUserIdsByMemberConfig(userTaskConfig.getApproverConfigs(), workflowSchemaConfig.getChildNodeConfig(), delegateTask.getProcessInstanceId());

            userIdsByMemberConfig.addAll(approveUserIds);
            List<Integer> noticePolicyConfig = userTaskConfig.getNoticePolicyConfigs();

            if (noticePolicyConfig.size() == 0) {
                return;
            }

            String noticePolicyConfigString = StrUtil.join(StringPool.UNDERSCORE, noticePolicyConfig);

            RedisUtil redisUtil = SpringUtil.getBean(RedisUtil.class);
            //推送次数设定为几次 就设置几个key值  然后计算过期时间
            for (Integer i = 0; i < timeoutRemidConfig.getPushHits(); i++) {


                // 公式为  （超时时间 + （间隔 * 第几次提醒）） * 3600秒
                // 第一次提醒 直接使用超时时间  所以  i == 0
                int expire = (timeoutRemidConfig.getHour() + (timeoutRemidConfig.getInterval() * i)) * 3600;

                // 格式为 timeout:{taskId}:{hit}:{noticePolicyConfigString}
                // taskId为任务id  hit为次数  noticePolicyConfigString为通知策略使用下划线隔开
                // 存储数据为所有需要推送的人员
                // expire 为过期时间
                redisUtil.set(WorkflowConstant.TIMEOUT_REMID_KEY + delegateTask.getId() + StringPool.COLON + (i + 1) + StringPool.COLON + noticePolicyConfigString, userIdsByMemberConfig, expire);
            }
        }
    }



}
